package cn.com.zetatech.loader.util;

import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;

import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;

@Slf4j
public class SftpClientUtil {


    private final static int BIG_BUFFER_SIZE = 1024 * 1024 * 2;

    public static Session sshSftpReadFile(String ip, String user, String psw,
                                          int port) {
        JSch jsch = new JSch();
        Session session = null;
        try {
            if (port <= 0) {
                // 连接服务器，采用默认端口
                session = jsch.getSession(user, ip);
            } else { // 采用指定的端口连接服务器
                session = jsch.getSession(user, ip, port);
            } // 如果服务器连接不上，则抛出异常
            if (session == null) {
                throw new Exception("session is null");
            } // 设置登陆主机的密码
            session.setPassword(psw);
            // 设置密码 // 设置第一次登陆的时候提示，可选值：(ask | yes | no)
            session.setConfig("StrictHostKeyChecking", "no");
            // 设置登陆超时时间
            session.connect(50000);
        } catch (Exception e) {
            log.info(e.getMessage());

        }
        return session;

    }


    public static void move(String ip, String user, String psw, int port, String directory, String newDirectory, String fileName) {

        if (null != newDirectory && newDirectory.contains("//")) {
            newDirectory = newDirectory.replace("//", "/");
        }
        Session session = sshSftpReadFile(ip, user, psw, port);
        ChannelSftp sftp = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect(30000);
            try {
                sftp.cd(directory);
                sftp.cd(newDirectory);
            } catch (Exception e) {
                log.info(e.getMessage());
                createDir(newDirectory, sftp);
            }

            sftp.cd(directory);

            sftp.rename(fileName, newDirectory + "/" + fileName);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("remove file error ");
        }
    }

    public static List<String> moves(String ip, int port, String user, String psw, String directory, String newDirectory,
                                     Boolean checkFileComplete,
                                     Map<String, Long> fileAndSizeMap, Function<String, String> newFileNameFunction) {
        List<String> moveFileNames = new ArrayList<>();
        if (null != newDirectory && newDirectory.contains("//")) {
            newDirectory = newDirectory.replace("//", "/");
        }
        Session session = sshSftpReadFile(ip, user, psw, port);
        ChannelSftp sftp = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect(30000);
            try {
                sftp.cd(directory);
                sftp.cd(newDirectory);
            } catch (Exception e) {
                log.info(e.getMessage());
                createDir(newDirectory, sftp);
            }
            sftp.cd(directory);
            List<ChannelSftp.LsEntry> files = new ArrayList<>();
            if (fileAndSizeMap == null || fileAndSizeMap.isEmpty()) {
                sftp.ls(directory, entry -> {
                            boolean test = !entry.getAttrs().isDir();
                            if (test) {
                                files.add(entry);
                            }
                            return 0;
                        }
                );
            } else {
                sftp.ls(directory, entry -> {
                            boolean test = !entry.getAttrs().isDir() && fileAndSizeMap.containsKey(entry.getFilename());
                            if (test) {
                                files.add(entry);
                            }
                            return 0;
                        }
                );
            }

            if (files.isEmpty()) {
                return new ArrayList<>();
            }
            for (ChannelSftp.LsEntry file : files) {
                boolean canMove = false;
                String fileName = file.getFilename();
                long fileSize = file.getAttrs().getSize();
                if (fileAndSizeMap != null && fileAndSizeMap.containsKey(fileName)) {
                    if (fileSize > 0 && fileSize == fileAndSizeMap.get(fileName)) {
                        log.info("文件大小与预估一致，开始移动,文件名：{}", fileName);
                        canMove = true;
                    }else{
                        log.info("文件大小与预估不一致，文件：{}", fileName);
                    }
                }
                if (!canMove) {
                    if (checkFileComplete) {
                        if (fileSize == 0L) {
                            log.error("文件大小为0，忽略本次文件：{}", fileName);
                            continue;
                        }
                        Thread.sleep(200L);
                        SftpATTRS lstat2 = sftp.lstat(fileName);
                        if (lstat2 == null || lstat2.getSize() != fileSize) {
                            log.error("文件大小变化中，忽略本次文件：{}", fileName);
                            continue;
                        }
                        canMove = true;
                    }
                }
                if (canMove) {
                    String newFileName = newFileNameFunction != null ? newFileNameFunction.apply(fileName) : fileName;
                    sftp.rename(fileName, newDirectory + "/" + newFileName);
                    moveFileNames.add(newFileName);
                    log.info("SFTP文件：{} 移动到：{} 成功", directory + "/" + fileName, newDirectory + "/" + newFileName);
                }
            }
            log.info("move success ！");
            return moveFileNames;
        } catch (Exception e) {
            log.info("move file error ", e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
        }
        return new ArrayList<>();
    }

    public static List<String> copyFiles(String ip, int port, String user, String psw, String directory, String newDirectory,
                                         Boolean checkFileComplete,
                                         Map<String, Long> fileAndSizeMap, Function<String, String> newFileNameFunction) {
        List<String> moveFileNames = new ArrayList<>();
        if (null != newDirectory && newDirectory.contains("//")) {
            newDirectory = newDirectory.replace("//", "/");
        }
        Session session = sshSftpReadFile(ip, user, psw, port);
        ChannelSftp sftp = null;
        ChannelExec exec = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect(30000);
            try {
                sftp.cd(directory);
                sftp.cd(newDirectory);
            } catch (Exception e) {
                log.info(e.getMessage());
                createDir(newDirectory, sftp);
            }
            sftp.cd(directory);
            List<String> fileNames = new ArrayList<>();
            if (fileAndSizeMap == null || fileAndSizeMap.isEmpty()) {
                sftp.ls(directory, entry -> {
                            boolean test = !entry.getAttrs().isDir();
                            if (test) {
                                fileNames.add(entry.getFilename());
                            }
                            return 0;
                        }
                );
            } else {
                sftp.ls(directory, entry -> {
                            boolean test = !entry.getAttrs().isDir() && fileAndSizeMap.containsKey(entry.getFilename());
                            if (test) {
                                fileNames.add(entry.getFilename());
                            }
                            return 0;
                        }
                );
            }
            if (fileNames.isEmpty()) {
                return new ArrayList<>();
            }
            for (String fileName : fileNames) {
                SftpATTRS lstat1 = sftp.lstat(fileName);
                if (lstat1.isDir()) {
                    continue;
                }
                boolean canOperate = false;
                long fileSize = lstat1.getSize();
                if (fileAndSizeMap != null && !fileAndSizeMap.isEmpty()) {
                    if (fileSize != 0L && fileAndSizeMap.getOrDefault(fileName, 0L).equals(fileSize)) {
                        log.info("文件大小与预估一致，开始移动,文件名：{}", fileName);
                        canOperate = true;
                    }else{
                        log.info("文件大小与预估不一致，文件：{}", fileName);
                    }
                }
                if (!canOperate) {
                    if (checkFileComplete) {
                        if (fileSize == 0L) {
                            log.error("文件大小为0，忽略本次文件：{}", fileName);
                            continue;
                        }
                        Thread.sleep(200L);
                        SftpATTRS lstat2 = sftp.lstat(fileName);
                        if (lstat2 == null || lstat2.getSize() != fileSize) {
                            log.error("文件大小变化中，忽略本次文件：{}", fileName);
                            continue;
                        }
                        canOperate = true;
                    }
                }
                if (canOperate) {
                    String newFileName = newFileNameFunction != null ? newFileNameFunction.apply(fileName) : fileName;
                    try {
                        exec = (ChannelExec) session.openChannel("exec");
                        exec.setCommand("cp " + directory + "/" + fileName + " " + newDirectory + "/" + newFileName);
                        exec.connect();
                        log.info("SFTP文件：{} 复制到：{} 成功", directory + "/" + fileName, newDirectory + "/" + newFileName);
                        moveFileNames.add(newFileName);
                        exec.disconnect();
                    } catch (JSchException e) {
                        log.info("SFTP文件：{} 复制到：{} 失败", directory + "/" + fileName, newDirectory + "/" + newFileName);
                    } finally {
                        if (exec != null) {
                            if (exec.isConnected()) {
                                exec.disconnect();
                            }
                        }
                    }
                }
            }
            log.info("copy success ！");
            return moveFileNames;
        } catch (Exception e) {
            log.info("copy file error ", e);
        } finally {
            if (exec != null) {
                if (exec.isConnected()) {
                    exec.disconnect();
                }
            }
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
        return new ArrayList<>();
    }

    public static String getFiles(Session session, String sPath, Predicate<ChannelSftp.LsEntry> fileEntryFilter, HashMap<String, byte[]> result) {
        String maxTime = "";
        List<ChannelSftp.LsEntry> list = new ArrayList<>();
        ChannelSftp sftp = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect(30000);
            try {
                sftp.cd(sPath);
            } catch (SftpException e) {
                log.info(e.getMessage());
                createDir(sPath, sftp);
                sftp.cd(sPath);
            }
            ChannelSftp.LsEntrySelector selector = entry -> {
                if (fileEntryFilter.test(entry)) {
                    list.add(entry);
                }
                return 0;
            };
            sftp.ls(sPath, selector);
            Date maxDate = null;
            for (ChannelSftp.LsEntry file : list) {
                if (!file.getFilename().equals("..") && !file.getFilename().equals(".")) {
                    Date dateModify = new Date(file.getAttrs().getMTime() * 1000L);
                    if (maxDate == null) {
                        maxDate = dateModify;
                    } else if (dateModify.compareTo(maxDate) > 0) {
                        maxDate = dateModify;
                    }
                    InputStream inputStream = sftp.get(sftp.pwd() + "/" + file.getFilename());
                    result.put(file.getFilename(), SftpClientUtil.read(inputStream));
                }
            }
            if (maxDate != null) {
                maxTime = new SimpleDateFormat("yyyyMMddHHmmss").format(maxDate);
            }
        } catch (Exception e) {
            log.info("", e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
        return maxTime;
    }


    /**
     * 读取流信息
     *
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static byte[] read(InputStream inputStream) throws IOException {
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024 * 1024 * 10];
            //System.out.println(inputStream.available());
            int num = inputStream.read(buffer);
            int i = 0;
            while (num != -1) {
                baos.write(buffer, 0, num);
                num = inputStream.read(buffer);
            }
            baos.flush();
            byte[] bytes = baos.toByteArray();
            return bytes;
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (baos != null) {
                baos.close();
            }
        }
    }

    /**
     * 获取sftp上的文件
     *
     * @param remoteBaseDir
     * @param fileEntryFilter
     * @return
     * @throws Exception
     */
    public static List<String> getFiles(Session session, String localBaseDir, String remoteBaseDir, Predicate<ChannelSftp.LsEntry> fileEntryFilter) throws Exception {
        List<String> fileNames = new ArrayList<>();
        HashMap<String, byte[]> streams = new HashMap<>();
        String maxTime = getFiles(session, remoteBaseDir, fileEntryFilter, streams);
        for (String fileName : streams.keySet()) {
            byte[] byt = streams.get(fileName);
            if (byt != null && byt.length > 0) {
                File file = null;
                FileOutputStream output = null;
                BufferedOutputStream bufferedOutput = null;
                try {
                    //判断文件夹是否存在
                    File localfile = new File(localBaseDir);
                    if (!localfile.exists()) {
                        localfile.mkdirs();
                    }
                    file = new File(localBaseDir + fileName);
                    output = new FileOutputStream(file);
                    bufferedOutput = new BufferedOutputStream(output);
                    bufferedOutput.write(byt);
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                } finally {
                    if (output != null) {
                        try {
                            output.flush();
                            output.close();
                        } catch (IOException e) {
                            log.error(e.getMessage());
                        }
                    }

                    if (bufferedOutput != null) {
                        try {
                            bufferedOutput.flush();
                            bufferedOutput.close();
                        } catch (IOException e) {
                            log.error(e.getMessage());
                        }
                    }
                }
            }
            fileNames.add(fileName);
        }

        return fileNames;
    }

    /**
     * 远程获取文件流
     */
    public static byte[] readFile(String ip, String user, String psw, int port, String remoteDir, String fileName) throws Exception {

        Session session = sshSftpReadFile(ip, user, psw, port);
        ChannelSftp sftp = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect(30000);
            sftp.cd(remoteDir);
            InputStream inputStream = sftp.get(sftp.pwd() + "/" + fileName);
            return SftpClientUtil.read(inputStream);
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }

    /**
     * 将输入流的数据上传到sftp作为文件。文件完整路径=basePath+directory
     *
     * @param basePath     服务器的基础路径
     * @param directory    上传到该目录
     * @param sftpFileName sftp端文件名
     */
    public static void upload(String ip, String user, String psw, int port,
                              String basePath, String directory, String sftpFileName, InputStream input) throws SftpException {

        Session session = sshSftpReadFile(ip, user, psw, port);

        Channel channel = null;
        ChannelSftp sftp = null;

        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;


            Class cl = ChannelSftp.class;
            Field field = cl.getDeclaredField("server_version");
            field.setAccessible(true);
            field.set(sftp, 2);
            sftp.setFilenameEncoding("GBK");
            sftp.cd(basePath);
            sftp.cd(directory);
        } catch (Exception e) {
            //目录不存在，则创建文件夹
            String[] dirs = directory.split("/");
            String tempPath = basePath;
            for (String dir : dirs) {
                if (null == dir || "".equals(dir)) {
                    continue;
                }
                tempPath += "/" + dir;
                try {
                    sftp.cd(tempPath);
                } catch (SftpException ex) {
                    createDir(tempPath, sftp);
                    sftp.cd(tempPath);
                }
            }
        }
        sftp.put(input, sftpFileName); //上传文件
    }

    /**
     * 文件上传
     *
     * @param ip
     * @param user
     * @param psw
     * @param port
     * @param remoteDir
     * @param sftpFileName
     * @param input
     */
    public static void upload(String ip, String user, String psw, int port, String remoteDir, String sftpFileName, InputStream input) throws Exception {

        Session session = sshSftpReadFile(ip, user, psw, port);

        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            createDir(remoteDir, sftp);
            sftp.cd(remoteDir);
            try {
                //删除远程目录中的同名文件
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            } catch (Exception e) {
                log.error("", e);
            }
            sftp.put(input, sftpFileName);
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }


    /**
     * 文件上传,上传文件夹下所有文件
     *
     * @param remoteDir
     * @param files
     */
    public static void upload(Session session, String remoteDir, List<File> files) throws Exception {

        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            remoteDir = remoteDir.replace("\\", "/");
            createDir(remoteDir, sftp);
            sftp.cd(remoteDir);

            FileInputStream inputStream;
            for (File file : files) {
                inputStream = new FileInputStream(file);
                sftp.put(inputStream, file.getName(), 0);
                inputStream.close();
            }
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
                if (channel.isConnected()) {
                    channel.disconnect();
                }
            }
        }
    }


    /**
     * 文件上传
     *
     * @param remoteDir
     * @param sftpFileName
     * @param input
     */
    public static void upload(Session session, String remoteDir, String sftpFileName, InputStream input) throws Exception {

        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            remoteDir = remoteDir.replace("\\", "/");
            createDir(remoteDir, sftp);
            sftp.cd(remoteDir);
            try {
                //删除远程目录中的同名文件
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            } catch (Exception e) {

            }
            sftp.put(input, sftpFileName);
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (input != null) {
                input.close();
            }
        }
    }

    public static void disconnect(Session session) {
        if (session != null) {
            if (session.isConnected()) {
                session.disconnect();
            }
        }
    }

    public static String uploadReturnFileName(String ip, String user, String psw, int port, String remoteDir, String sftpFileName, InputStream input) throws Exception {

        Session session = sshSftpReadFile(ip, user, psw, port);

        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            createDir(remoteDir, sftp);
            sftp.cd(remoteDir);
            try {
                //删除远程目录中的同名文件
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            } catch (Exception e) {
                log.error("", e);
            }
            sftp.put(input, sftpFileName);
        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
            return sftp.pwd() + "/" + sftpFileName;
        }
    }

    /**
     * 删除文件
     *
     * @param directory  要删除文件所在目录
     * @param deleteFile 要删除的文件
     */
    public static void deleteFile(String ip, String user, String psw, int port, String directory, String deleteFile) {
        Session session = sshSftpReadFile(ip, user, psw, port);

        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            sftp.cd(directory);
            sftp.rm(new String(deleteFile.getBytes(StandardCharsets.ISO_8859_1)));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("Delete error");
        }

    }

    /**
     * 删除某个文件
     *
     * @param ip
     * @param user
     * @param psw
     * @param port
     * @param remoteDir
     * @param sftpFileName
     * @throws Exception
     */
    public static void delete(String ip, String user, String psw, int port, String remoteDir, String sftpFileName) throws Exception {
        Session session = sshSftpReadFile(ip, user, psw, port);

        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            sftp.cd(remoteDir);
            //删除远程目录中的同名文件
            try {
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            } catch (Exception e) {
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            }

        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }


    /**
     * 删除某个文件
     *
     * @param remoteDir
     * @param sftpFileName
     * @throws Exception
     */
    public static void delete(Session session, String remoteDir, String sftpFileName) throws Exception {
        Channel channel = null;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            sftp.cd(remoteDir);
            //删除远程目录中的同名文件
            try {
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            } catch (Exception e) {
                sftp.rm(sftp.pwd() + "/" + sftpFileName);
            }

        } catch (Exception e) {
            log.error("", e);
            throw new RuntimeException(e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }


    /**
     * 创建一个文件目录
     *
     * @throws
     */
    public static void createDir(String remoteDir, ChannelSftp sftp) {
        try {
            if (isDirExist(remoteDir, sftp)) {
            } else {
                String[] pathArry = remoteDir.split("/");
                StringBuffer filePath = new StringBuffer("/");
                for (String path : pathArry) {
                    if (path.equals("")) {
                        continue;
                    }

                    filePath.append(path + "/");
                    if (isDirExist(filePath.toString(), sftp)) {
                        sftp.cd(filePath.toString());
                    } else {
                        // 建立目录
                        sftp.mkdir(filePath.toString());
                        // 进入并设置为当前目录
                        sftp.cd(filePath.toString());
                    }
                }

            }

        } catch (Exception e) {
            throw new RuntimeException("创建路径错误:" + remoteDir, e);
        }

    }


    /**
     * 判断目录是否存在
     */
    public static boolean isDirExist(String directory, ChannelSftp sftp) {
        boolean isDirExistFlag = false;
        try {
            SftpATTRS sftpATTRS = sftp.lstat(directory);
            isDirExistFlag = true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().equalsIgnoreCase("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }

    /**
     * 获取sftp上的文件
     *
     * @param ip
     * @param user
     * @param psw
     * @param port
     * @param localBaseDir
     * @param remoteBaseDir
     * @param timestamp
     * @return
     * @throws Exception
     */
    public static String getBigFiles(String ip, String user, String psw, int port, String localBaseDir, String remoteBaseDir, String timestamp) throws Exception {
        String maxTime = "";
        Session session = sshSftpReadFile(ip, user, psw, port);
        List<ChannelSftp.LsEntry> list = new ArrayList<>();
        ChannelSftp sftp = null;
        log.info("quartz loader data 链接SFTP服务 START 从：" + localBaseDir + "下载文件到：" + remoteBaseDir);
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
            sftp.connect(30000);
            try {
                log.info("quartz loader data 切换到文件：" + remoteBaseDir);
                sftp.cd(remoteBaseDir);
            } catch (SftpException e) {
                log.info("quartz loader data 切换到文件：" + remoteBaseDir + "失败，文件不存在，新建文件夹");
                createDir(remoteBaseDir, sftp);
                sftp.cd(remoteBaseDir);
            }

            log.info("quartz loader data 链接SFTP服务开始从：" + remoteBaseDir + "下载文件到：" + localBaseDir);
            ChannelSftp.LsEntrySelector selector = new ChannelSftp.LsEntrySelector() {
                @Override
                public int select(ChannelSftp.LsEntry entry) {
                    if ("success".equals(entry.getFilename()) || "error".equals(entry.getFilename())) {
                        return 0;
                    }
                    if (timestamp == null || timestamp.equals("")) {
                        log.info("quartz loader data 链接SFTP服务开始从：" + remoteBaseDir + "下载所有文件");
                        list.add(entry);
                    } else {
                        Date dateModify = new Date(entry.getAttrs().getMTime() * 1000L);
                        if (new SimpleDateFormat("yyyyMMddHHmmss").format(dateModify).compareTo(timestamp) > 0) {
                            log.info("quartz loader data 链接SFTP服务开始从：" + remoteBaseDir + "下载部分文件：" + entry.getFilename());
                            list.add(entry);
                        }
                    }
                    return 0;
                }
            };
            sftp.ls(remoteBaseDir, selector);

            log.info("quartz loader data 链接SFTP服务开始从：" + remoteBaseDir + "下载文件总数：" + list.size());
            Date maxDate = null;
            for (ChannelSftp.LsEntry file : list) {
                log.info("quartz loader data 链接SFTP服务开始从：" + remoteBaseDir + "下载文件");
                if (!file.getFilename().equals("..") && !file.getFilename().equals(".")) {
                    Date dateModify = new Date(file.getAttrs().getMTime() * 1000L);
                    log.info("文件名称：" + file.getFilename() + ", 修改日期：" + dateModify);
                    if (maxDate == null) {
                        maxDate = dateModify;
                    } else if (dateModify.compareTo(maxDate) > 0) {
                        maxDate = dateModify;
                    }

                    File localfile = new File(localBaseDir);
                    if (!localfile.exists()) {
                        localfile.mkdirs();
                    }
                    sftp.get(sftp.pwd() + "/" + file.getFilename(), localBaseDir + file.getFilename());
                    new File(localBaseDir + file.getFilename()).setLastModified(file.getAttrs().getMTime() * 1000L);
//                    BufferedInputStream inputStream = new BufferedInputStream(sftp.get(sftp.pwd() + "/"+ file.getFilename()),BIG_BUFFER_SIZE);
//                    createFile(inputStream,localBaseDir,file.getFilename(),file.getAttrs().getSize());
                }
            }

            log.info("quartz loader data 链接SFTP服务 END 从：" + remoteBaseDir + "下载文件到：" + localBaseDir);
            if (maxDate != null) {
                maxTime = new SimpleDateFormat("yyyyMMddHHmmss").format(maxDate);
            }
        } catch (Exception e) {
            log.info("获取sftp上的文件异常", e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
        return maxTime;

    }

    public static void createFile(BufferedInputStream inputStream, String localBaseDir, String fileName, long fileSize) {
        if (inputStream != null) {
            File file = null;
            FileOutputStream output = null;
            BufferedOutputStream bufferedOutput = null;
            try {
                //判断文件夹是否存在
                File localfile = new File(localBaseDir);
                if (!localfile.exists()) {
                    localfile.mkdirs();
                }
                file = new File(localBaseDir + fileName);
                output = new FileOutputStream(file);
                bufferedOutput = new BufferedOutputStream(output);
                byte[] buffer = new byte[BIG_BUFFER_SIZE];
                int num = inputStream.read(buffer);
                while (num != -1) {
                    bufferedOutput.write(buffer, 0, num);
                    num = inputStream.read(buffer);

                }
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            } finally {
                if (output != null) {
                    try {
                        output.flush();
                        output.close();
                    } catch (IOException e) {
                        log.error(e.getMessage());
                    }
                }

                if (bufferedOutput != null) {
                    try {
                        bufferedOutput.flush();
                        bufferedOutput.close();
                    } catch (IOException e) {
                        log.error(e.getMessage());
                    }
                }

                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        log.error(e.getMessage());
                    }
                }
            }
        }
    }


    public static void deleteLessThanTime(String ip, String user, String psw, int port, String remoteDir, Date time) throws Exception {
        Session session = sshSftpReadFile(ip, user, psw, port);
        Channel channel;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            sftp.cd(remoteDir);
            Vector<ChannelSftp.LsEntry> lsFile = sftp.ls(remoteDir);
            for (ChannelSftp.LsEntry entry : lsFile) {
                String fileName = entry.getFilename();
                if (".".equals(fileName) || "..".equals(fileName)) {
                    continue;
                }
                Date dateModify = new Date(((long) entry.getAttrs().getMTime()) * 1000L);
                //删除比指定日期小的文件
                if (dateModify.compareTo(time) < 0) {
                    try {
                        sftp.rm(sftp.pwd() + "/" + fileName);
                    } catch (Exception e) {
                        log.error("deleteLessThanTime delete " + remoteDir + "/" + fileName + "error", e);
                    }
                }
            }
        } catch (Exception e) {
            log.error("deleteLessThanTime error", e);
        } finally {
            if (sftp != null) {
                if (sftp.isConnected()) {
                    sftp.disconnect();
                }
            }
            if (session != null) {
                if (session.isConnected()) {
                    session.disconnect();
                }
            }
        }
    }

    /**
     * 下载文件
     *
     * @param directory 下载目录
     * @return 字节数组
     */
    public static InputStream download(String ip, String user, String psw, int port,
                                       String directory, String downloadFile) throws SftpException, IOException {
        Session session = sshSftpReadFile(ip, user, psw, port);
        Channel channel;
        ChannelSftp sftp = null;
        try {
            channel = session.openChannel("sftp");
            channel.connect(30000);
            sftp = (ChannelSftp) channel;
            if (directory != null && !"".equals(directory)) {
                sftp.cd(directory);
            }
            //SftpATTRS lstat = sftp.lstat(downloadFile);
            return sftp.get(downloadFile);
        } catch (Exception e) {
            return null;
        }
    }


    public static void main(String[] args) {
        List<String> filenames = new ArrayList<>();
        filenames.add("a.txt1");
        filenames.add("b.txt1");
        Map<String, Long> fileAndSizeMap = new HashMap<>();
        fileAndSizeMap.put("a.txt1", 10L);
        fileAndSizeMap.put("b.txt1", 11L);
//        copyFiles("10.10.104.159", 22, "root", "bddemo@2023",
//                "/dmsData/testSftp0616/A", "/dmsData/testSftp0616/B",
//                false, fileAndSizeMap, s -> {
//                    return s + 1;
//                });
        moves("10.10.104.159", 22, "root", "bddemo@2023",
                "/dmsData/testSftp0616/A", "/dmsData/testSftp0616/C",
                true, fileAndSizeMap, s -> {
                    return s + 1;
                });
    }


}
